# @FileName  : tool.py
# @Time      : 2021/7/14 0014  18:15
# @Author    : LuZhaoHui
# @Software  : PyCharm

from os import environ

environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1'

from PyQt5.QtCore import *
from configparser import ConfigParser
import threading
import locale, re, os
import numpy, natsort
import csv, codecs
import sys, paramiko, datetime, hashlib, uuid
import inspect, ctypes, ast, xlsxwriter, openpyxl, json
# from mutagen.mp3 import MP3
from core.histogram import *

WINDOW_SIZE = (1792, 972)
BIN_PHOTO = 'photoRun'
BIN_UP = 'up'
LOG_UP = 'update-linux.log'
PHOTOINI = 'photo.ini'
KEYINI = 'key.ini'
PRINT_WINDOW_SIZE = (7680, 4320)
# EXE_PATH = os.path.abspath(os.getcwd())
BIN_PATH = os.path.dirname(sys.argv[0])
BASE_PATH = os.path.dirname(BIN_PATH)
sys.path.append(BASE_PATH)
CONF_PATH = os.path.join(BASE_PATH, 'conf').replace('\\', '/')
CONF_DEFAULT = 'default'
OP_PASSWORD = 'dashen'
WORK_PATH = os.path.join(BASE_PATH, 'work').replace('\\', '/')
CHECK_PATH = os.path.join(BASE_PATH, 'check').replace('\\', '/')
IMG_PATH = os.path.join(BASE_PATH, 'img').replace('\\', '/')
CACHE_PATH = os.path.join(BASE_PATH, 'cache').replace('\\', '/')
LOG_PATH = os.path.join(BASE_PATH, 'log').replace('\\', '/')
LOGO = os.path.join(BASE_PATH, 'ui/LOGO.png').replace('\\', '/')
TITLELOGO = os.path.join(BASE_PATH, 'ui/title.png').replace('\\', '/')
IMAGEDEMO0 = os.path.join(BASE_PATH, 'ui/image0.jpg').replace('\\', '/')

DEBUG = True if sys.gettrace() else False
# UIMDLL = os.path.join(BASE_PATH, 'core/UISimCanFunc.dll').replace('\\', '/')

# D8_PATH = os.path.join(BASE_PATH, 'D8').replace('\\', '/')

MAX_PRINTNUMS = 5
IMG_WORK = 'work'
IMG_WORK_FOLDER = ('Prefix', 'Main', 'Suffix')
IMG_WORK_REMARK = ('前标', '正文', '后标')
WEB_WORK_UPDIR_NUMS = 300

# 判断胶片类型:35MM,16MM,3xMM
IMG_TYPE = ("16", "35", "3x")
IMG_PICTYPE = ("半幅", "全幅")
IMG_STATE = ("", "错误图片", "测试图片")
IMG_EXTS = (".jpg", ".tiff", ".tif")
IMG_FORMAT = ("JPEG", "TIFF", "TIFF")
PAPER_LETTER = {'A0': (33.11, 46.81),
                'B1': (27.83, 39.37),
                'A1': (23.39, 33.11),
                'B2': (19.69, 27.83),
                'A2': (16.54, 23.39),
                'B3': (13.90, 19.69),
                'A3': (11.69, 16.54),
                'B4': (9.84, 13.90),
                'A4': (8.27, 11.69),
                'A5': (5.82, 8.26),
                'A6': (4.13, 5.82)}

# 图片信息：段标识(1-0xff)+段类型(1-IMG_XXXX)+段长度(2)+段内容(n)
# 段类型
IMG_MARK = 0xff  # 段标识
IMG_SOI = 0xd8  # 文件头
IMG_APP0 = 0xe0  # 定义交换格式和图像识别信息
IMG_APP1 = 0xe1  #
IMG_APPF = 0xef  #
IMG_DQT = 0xdb  # 定义量化表
IMG_DRI = 0xdd  # 定义重新开始间隔
IMG_SOF0 = 0xc0  # 帧开始
IMG_SOF1 = 0xc1
IMG_DHT = 0xc4  # 定义HUFFMAN表
IMG_SOS = 0xda  # 扫描行开始
IMG_EOI = 0xd9  # 文件尾
IMG_COM = 0xfe  # 注释


def listStrToFloat(listStr):
    return [float(s) for s in listStr]

def listStrToInt(listStr):
    return [int(s) for s in listStr]

def getExtFormat(ext):
    index = IMG_EXTS.index(ext)
    if index < 0:
        index = 0
    return IMG_FORMAT[index]


def getVerExe(ver):
    return '%s_%s%s' % (os.path.splitext(BIN_PHOTO)[0], ver, os.path.splitext(BIN_PHOTO)[1])


def isPrintWindow(w, h):
    return PRINT_WINDOW_SIZE[0] == w and PRINT_WINDOW_SIZE[1] == h


def curFunc(err):
    return '%s:%s' % (sys._getframe().f_code.co_name, str(err))


def filenameSort(s):
    name = s
    try:
        for ex in IMG_EXTS:
            if s.index(ex) >= 0:
                name = s[:s.index(IMG_EXTS[0])]
                break
    except Exception as e:
        name = s
    n = name.count('-')
    p = '(\\d+)(\\D+)' * n + '(\\d+)'
    s1 = re.findall(p, name)
    if not isinstance(s1[0], tuple):
        s1[0] = (s1[0],)
    s11 = re.findall(r'[A-Za-z0-9]+', s)
    s2 = sum(s1, ())
    s3 = [int(s) if s.isdigit() else s for s in s2]
    return s3 + s11


def winSort(flist):
    try:
        return sorted(flist, key=filenameSort)
    except Exception as e:
        return flist


def natSort(flist):
    locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8')
    return natsort.natsorted(flist,
                             # key=lambda x: x.replace('(', '@').replace(')', ''),
                             key=lambda x: x.split('-'),
                             alg=natsort.ns.PATH | natsort.ns.LOCALE | natsort.ns.IGNORECASE)


def isD8():
    return 'D8_PATH' in dir()


def getUuid():
    return uuid.uuid1().hex


def getStrMd5(str):
    md5 = hashlib.md5()
    md5.update(str.encode('utf8'))
    return md5.hexdigest()


def getDictToStr(dict, key):
    if key in dict.keys():
        return dict[key]
    return ''


def getDictToInt(dict, key):
    if key in dict.keys():
        return dict[key]
    return 0


def getAddListPath(path, flist):
    dirs = []
    for f in flist:
        dirs.append(pathJoin(path, f))
    return dirs


def getDirSortList(dir, isSort):
    list = []
    if os.path.exists(dir):
        for d in os.listdir(dir):
            name = pathJoin(dir, d)
            # isNum = d.isnumeric()
            if os.path.isdir(name):
                list.append(d)
                # if d.isnumeric():
                #     print(d)
        if len(list) > 0 and isSort:
            try:
                # list = winSort(list)
                list = natSort(list)
            except Exception as e:
                pass
                # print(e)
    return list


def getFileSortList(dir, isSort=True):
    list = []
    if os.path.exists(dir):
        list = os.listdir(dir)
        if len(list) > 0 and isSort:
            try:
                list = winSort(list)
                # list = natSort(list)
                # list.sort(key=lambda x: int(x) if x.isnumeric() else x)
            except Exception as e:
                pass
                # print(e)
    return list


def deleteFile(name):
    if os.path.exists(name):
        os.remove(name)


def getDirParentSortList(dir):
    return getDirSortList(os.path.dirname(dir), True)


def getListDir(dirs):
    # msg = eval(dirs)
    msg = dirs.split(',')
    if isinstance(msg, str):
        if os.path.exists(msg):
            return msg
    else:
        for s in msg:
            if os.path.exists(s):
                return s
        return ''


def putListDir(dir, dirs):
    varList = dirs.split(',')
    for s in varList:
        if s == dir:
            return False, dirs
    msg = dir
    for i, s in enumerate(varList):
        if i >= 3:
            break
        msg += ',' + s
    return True, msg


def getPath1(path):
    return os.path.dirname(os.path.dirname(path))


def getPath2(path):
    return os.path.dirname(getPath1(path))


def getWorkName(name):
    if name[:(len(IMG_WORK) + 1)] != IMG_WORK + '_':
        return IMG_WORK + '_' + name
    return name


def format_number(amount):
    zheng = str(amount)
    res = []
    while True:
        if len(zheng) > 3:
            str1 = zheng[-3:]
            zheng = zheng[0:len(zheng) - 3]
            res.insert(0, str1)
        else:
            res.insert(0, zheng)
            break
    result = ','.join(res)
    return result


def getSizeByteToKb(byte):
    return int((byte + 512) / 1024)


def getPixToW(pix):
    return int((pix + 5000) / 10000)


def getStepToRangeMm(step):
    return (step / 1000 * 20.0)


def getRangeMmToStep(mm):
    return int(mm * 1000 / 20.0)


def findImgType(ts):
    for i, t in enumerate(IMG_TYPE):
        if ts == t:
            return i
    return 0


def getImgType0(tp):
    if tp == 0 or tp == 1 or tp == 2:
        return IMG_TYPE[tp]
    return "00"


def getImgType(tp):
    if tp == 0 or tp == 1 or tp == 2:
        return IMG_TYPE[tp] + 'MM'
    return "00MM"


def getImgPicType(hf):
    if hf == 0 or hf == 1:
        return IMG_PICTYPE[hf]
    return "非标"


def getWorkPath(dir):
    index = -1
    try:
        index = IMG_WORK_FOLDER.index(dir)
    except Exception as e:
        index = -1
    return index


# 项目目录
def isWorkPath(dir):
    if not os.path.exists(dir):
        return [], []
    dlist = ['', '', '']
    flist = [[], [], []]
    for f in os.listdir(dir):
        d = pathJoin(dir, f)
        if os.path.isdir(d):
            # 目录
            index = getWorkPath(f)
            if index < 0:
                continue
            dlist[index] = d
            for ff in os.listdir(d):
                dd = pathJoin(d, ff)
                if os.path.isfile(dd) and os.path.splitext(dd)[1] in IMG_EXTS:
                    flist[index].append(dd)
            continue
        if os.path.isfile(d) and os.path.splitext(d)[1] in IMG_EXTS:
            # 图片
            flist[1].append(d)
    return dlist, flist


def getPaper(s, d):
    if d[0] > 0 and d[1] > 0:
        w = s[0] / d[0]
        h = s[1] / d[1]
        for k, v in PAPER_LETTER.items():
            v0 = v[0] / 10
            v1 = v[1] / 10
            if (v[0] - v0) < w < (v[0] + v0) and (v[1] - v1) < h < (v[1] + v1):
                return k
            if (v[0] - v0) < h < (v[0] + v0) and (v[1] - v1) < w < (v[1] + v1):
                return k
    return ''


def pathJoin(path1, path2):
    return os.path.join(path1, path2).replace('\\', '/')


def listFind(list, item):
    try:
        index = list.index(item)
    except ValueError:
        index = -1
    return index


def trimList(list):
    index = [i for i, x in enumerate(list) if x == '' or x == ' ']
    for i in index[::-1]:
        del list[i]
    return list


def removeLast(text):
    return text[:text[:-1].rindex('\n') - len(text)]


def strRight(str, slen):
    s = str
    if len(str) > slen:
        s = '...' + str[(len(str) - slen):]
    return s


def getImgReserve(image):
    # 图像转矩阵 并反色
    matrix = 255 - np.asarray(image)
    # 矩阵转图像
    return Image.fromarray(matrix)


def getImgAvGvSv(file):
    # image = cv2.imread(file)
    image = cv2.imdecode(numpy.fromfile(file, dtype=numpy.uint8), -1)
    # 亮度
    av = 0
    try:
        hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
        H, S, V = cv2.split(hsv)
        # 亮度非零的值
        v = V.ravel()[numpy.flatnonzero(V)]
        # 平均亮度
        av = sum(v) / len(v)
    except Exception as e:
        print(curFunc(e))
    # 灰度
    try:
        img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    except Exception as e:
        img = image
    w, h = img.shape
    size = img.size
    gv = 0
    p = [0] * 256
    for i in range(h):
        for j in range(w):
            gv += img[j][i]
            p[img[j][i]] += 1
    gv /= size
    # 对比
    m = 0
    for i in range(256):
        p[i] /= 256
        m += i * p[i]
    sv = 0
    for i in range(256):
        sv += (i - m) * (i - m) * p[i]
    return av, gv, sv


def getImg0File(file):
    size = [0, 0]
    unit = 0
    density = [0, 0]
    dot = [0, 0]
    c = 'RGB'
    with open(file, 'rb') as f:
        l = 64 * 1024
        data = f.read(l)
        i = 0
        while i < l:
            # i += 1
            if data[i] == IMG_MARK:
                i += 1
                continue
            elif data[i] == IMG_APP0:
                # 图像识别信息
                i += 1
                ch = data[i]
                cl = data[i + 1]
                len = ch * 256 + cl
                j = i + 2
                j += 5
                j += 2
                unit = data[j]
                j += 1
                ch = data[j]
                cl = data[j + 1]
                density[0] = ch * 256 + cl
                j += 2
                ch = data[j]
                cl = data[j + 1]
                density[1] = ch * 256 + cl
                j += 2
                dot[0] = data[j]
                j += 1
                dot[1] = data[j]
                i += len
                continue
            elif data[i] == IMG_COM or (data[i] >= IMG_APP1 and data[i] <= IMG_APPF):
                # 图像识别信息
                i += 1
                ch = data[i]
                cl = data[i + 1]
                len = ch * 256 + cl
                i += len
                continue
            elif data[i] == IMG_SOI:
                i += 1
                continue
            elif data[i] == IMG_DQT:
                i += 1
                ch = data[i]
                cl = data[i + 1]
                len = ch * 256 + cl
                i += len
                continue
            elif data[i] == IMG_SOF0:
                # 图像基本信息:段标识(1,FF),段类型(1,C0),段长度(2,8＋组件数量×3)
                i += 3
                # 样本精度(1,8),图片高度(2),图片宽度(2)
                i += 1
                ch = data[i]
                i += 1
                cl = data[i]
                size[1] = ch * 256 + cl
                i += 1
                ch = data[i]
                i += 1
                cl = data[i]
                size[0] = ch * 256 + cl
                # 组件数量(1,1＝灰度图，3＝YCbCr / YIQ,4＝CMYK),（以下每个组件占用３字节）
                i += 1
                if data[i] == 1:
                    c = 'L'
                break
            else:
                break
    return size + density + [c]


def writeXlsx(name, data):
    try:
        write = xlsxwriter.Workbook(name)
        sheet = write.add_worksheet()
        for i, cols in enumerate(data):
            for j, d in enumerate(cols):
                if isinstance(d, list):
                    l = len(d)
                    for k, dd in enumerate(d):
                        sheet.write(i, j * l + k, dd)
                else:
                    sheet.write(i, j, d)
        write.close()
    except Exception as e:
        print(curFunc(e))


def writeCsv(name, data):
    try:
        file_csv = codecs.open(name, 'w+', 'utf-8')
        writer = csv.writer(file_csv, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
        for d in data:
            writer.writerow(d)
    except Exception as e:
        print(curFunc(e))


def addCsv(name, data):
    try:
        file_csv = codecs.open(name, 'a', 'utf-8')
        writer = csv.writer(file_csv, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
        for d in data:
            writer.writerow(d)
    except Exception as e:
        print(curFunc(e))


def readXlsx(name):
    data = []
    if os.path.exists(name):
        read = openpyxl.load_workbook(name)
        sheets = read.get_sheet_names()
        sheet = read.get_sheet_by_name(sheets[0])
        rows = sheet.rows
        for row in rows:
            line = [col.value for col in row]
            data.append(line)
    return data


def readCsv(name, type=[]):
    data = []
    if os.path.exists(name):
        if os.path.exists(name):
            with open(name, encoding='utf-8') as csvfile:
                csv_reader = csv.reader(csvfile)
                cmd = 'data.append(row)'
                if len(type) > 0:
                    cmd = 'data.append(['
                    for i, t in enumerate(type):
                        if t == 'int':
                            cmd += 'int(row[%d]),' % (i)
                            continue
                        if t == 'float':
                            cmd += 'float(row[%d]),' % (i)
                            continue
                        cmd += 'row[%d],' % (i)
                    cmd = cmd[:-1] + '])'
                for row in csv_reader:
                    exec(cmd)
                    # data.append(row)
    return data


def retDirList(path):
    dirs = []
    if os.path.exists(path):
        for f in sorted(os.listdir(path)):
            if os.path.isdir(pathJoin(path, f)):
                dirs.append(f)
    return dirs


def retWorkList(path):
    dirs = []
    if os.path.exists(path):
        for f in sorted(os.listdir(path)):
            if os.path.isdir(pathJoin(path, f)):
                dirs.append(f)
        if len(dirs) == 0:
            f = 'work_test'
            os.mkdir(pathJoin(path, f))
            dirs.append(f)
    return dirs


def retWorkFileList(path):
    files = []
    if os.path.exists(path):
        for f in sorted(os.listdir(path)):
            name = pathJoin(path, f)
            if os.path.isfile(name) and os.path.splitext(name)[1] in IMG_EXTS:
                size = getImg2File(pathJoin(path, f))
                type = imgType(size[0], size[1])
                byte = GetFileByte(name)
                md5 = GetFileMd5(name)
                files.append([f, size[0], size[1], type, byte, md5])
    return files


def GetFileByte(file):
    info = QFileInfo(file)
    byte = info.size()
    return byte


def GetFileByteModify(file):
    info = QFileInfo(file)
    byte = info.size()
    modify = info.lastModified()
    return byte, modify


def GetFileMd5(file):
    md5 = ''
    size = 64 * 1024
    if os.path.isfile(file):
        with open(file, 'rb') as f:
            md5_obj = hashlib.md5()
            while True:
                d = f.read(size)
                if not d:
                    break
                md5_obj.update(d)
            hash_code = md5_obj.hexdigest()
            md5 = str(hash_code).lower()
    return md5


def GetFileEncrypt(file, type='sha1'):
    sha = ''
    if os.path.isfile(file):
        with open(file, 'rb') as f:
            hash_code = hashlib.new(type, f.read()).hexdigest()
            sha = str(hash_code).lower()
    return sha


def imgCheckWork(flist):
    # for i, f in enumerate(flist):
    pass


def imgType(w, h):
    w1 = int(w / 100)
    h1 = int(h / 100)
    if (w1 == 63 or w1 == 62) and (h1 == 43 or h1 == 4200):
        return 0
    if w1 == 42 and h1 == 28:
        return 1
    if w1 == 21 and h == 28:
        return 1
    if w1 == 28 and h == 21:
        return 1
    return 2


class MyParser(ConfigParser):
    "Inherit from built-in class: ConfigParser"

    def optionxform(self, optionstr):
        "Rewrite without lower()"
        return optionstr


def nowDateTime():
    return datetime.datetime.now()


def dateTimeStr(dtStr):
    return datetime.datetime.strptime(dtStr, '%Y-%m-%d %H:%M:%S')


def nowDateTime0():
    return datetime.datetime.combine(datetime.datetime.now(), datetime.time(0, 0, 0))


def nowDateTimeStr():
    return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')


def nowDateTimeInt():
    return int(datetime.datetime.now().strftime('%Y%m%d%H%M%S'))


def nowDateStr():
    return datetime.datetime.now().strftime('%Y-%m-%d')


def nowTimeStr():
    return datetime.datetime.now().strftime('%H:%M:%S')


def dateToInt(date):
    return int(date.toString('yyyyMMdd'))


def dateStrToFmt(dateStr):
    return '%s-%s-%s' % (dateStr[:4], dateStr[4:6], dateStr[-2:])


def timeStrToFmt(timeStr):
    return '%s:%s:%s' % (timeStr[:2], timeStr[2:4], timeStr[-2:])


def readJson(log=''):
    if len(log) == 0:
        file = LOG_PATH + '/json.json'
    else:
        file = LOG_PATH + '/' + log + '.json'
    with open(file, 'r', encoding='utf-8') as f:
        json_str = f.read()
        f.close()
    dict = json.loads(json_str)
    return dict


def saveJson(dict, log=''):
    if not os.path.exists(LOG_PATH):
        os.mkdir(LOG_PATH)
    if len(log) == 0:
        file = LOG_PATH + '/json.json'
    else:
        file = LOG_PATH + '/' + log + '.json'
    json_str = ''
    try:
        with open(file, 'w', encoding='utf-8') as f:
            json_str = json.dumps(dict, ensure_ascii=False)
            f.write(json_str)
    except Exception as e:
        print(e)
    return json_str


# def nowTime0Str():
#     return datetime.datetime.now().strftime('%H:%M:%S.%f')


def saveLog(msg, log=''):
    if not os.path.exists(LOG_PATH):
        os.mkdir(LOG_PATH)
    if len(log) == 0:
        file = LOG_PATH + '/' + nowDateStr() + '.log'
    else:
        file = LOG_PATH + '/' + log + '-' + nowDateStr() + '.log'
    logStr = ''
    try:
        with open(file, 'a', encoding='utf-8') as f:
            logStr = nowTimeStr() + ' ' + msg + '\n'
            f.write(logStr)
    except Exception as e:
        print(e)
    return logStr


def mmForm(mm):
    return '%d.%03d' % (int(mm / 1000), mm % 1000)


def secForm(sec):
    return '%02d:%02d:%02d' % (int(sec / 3600), int((sec % 3600) / 60), int(sec % 60))


# def getPhotoStepTime(plist, count, pos=-1):
#     canFullStep = plist[0]
#     canHalfStep = plist[1]
#     canSpaceStep = plist[2]
#     canStopTime = plist[3]
#     imgExposureTime = plist[4]
#     blackTime = plist[5]
#     canRate = plist[6]
#     canBeginStep = plist[7]
#     canEndStep = plist[8]
#     canPushStep = plist[9]
#     canPushRate = plist[10]
#     totalStep = 0
#     totalTime = 0
#     canStep = canFullStep
#     if canRate > 0:
#         # 计算步长和时间
#         t = canStopTime + blackTime + imgExposureTime
#         if pos < 0:
#             totalStep = canBeginStep + canEndStep + canStep * count
#             t2 = t * count / 1000
#             t1 = totalStep / canRate
#             if canPushRate > 0:
#                 t1 += (canPushStep * count * 2) / canPushRate
#         elif pos == count:
#             totalStep = canBeginStep + canEndStep + canStep * count
#             t2 = 0
#             t1 = 0
#         else:
#             totalStep = canBeginStep + canStep * pos
#             t2 = t * (count - pos) / 1000
#             t1 = (canBeginStep + canStep * (count - pos)) / canRate
#             if canPushRate > 0:
#                 t1 += (canPushStep * (count - pos) * 2) / canPushRate
#         totalTime = int(t1 + t2)
#
#     return totalStep, totalTime


def _async_raise(tid, exc_type):
    try:
        tid = ctypes.c_long(tid)
        if not inspect.isclass(exc_type):
            exc_type = type(exc_type)
        res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exc_type))
        if res == 0:
            raise ValueError("invalid thread id")
        elif res != 1:
            ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
            raise SystemError("PyThreadState_SetAsyncExc failed")
    except Exception as e:
        print(curFunc(e))


# 强制关闭线程的方法
def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)


class ReadDirImgFile(QThread):
    update_item = pyqtSignal(list)

    def __init__(self, dir):
        super().__init__()
        self.dir = dir

    def run(self):
        dirs = []
        if os.path.exists(self.dir):
            dirs = os.listdir(self.dir)
        self.update_item.emit([len(dirs)])
        for f in sorted(dirs):
            name = pathJoin(self.dir, f)
            if os.path.isfile(name) and os.path.splitext(name)[1] in IMG_EXTS:
                size = getImg2File(pathJoin(self.dir, f))
                type = imgType(size[0], size[1])
                byte = GetFileByte(name)
                md5 = GetFileMd5(name)
                self.update_item.emit([f, size[0], size[1], type, byte, md5])
        self.update_item.emit([])


class CheckWorkFile(QThread):
    update_item = pyqtSignal(list)

    def __init__(self, loadSsh, pos, fileList):
        super().__init__()
        self.ssh = loadSsh
        self.pos = pos
        self.flist = fileList

    def run(self):
        # 读目录
        if self.ssh.sshConnect() == 0:
            dirs = []
            workDir = self.ssh.workPath + '/' + self.ssh.workList[self.pos]
            for s in self.flist:
                # read md5
                md5 = self.ssh.getWorkFileMd5(workDir + '/' + s[0])
                self.update_item.emit(md5)
            self.ssh.sshClose()


class ReadWorkImgFile(QThread):
    update_item = pyqtSignal(list)

    def __init__(self, loadSsh, pos):
        super().__init__()
        self.ssh = loadSsh
        self.pos = pos

    def run(self):
        # 读目录
        if self.ssh.sshConnect() == 0:
            dirs = []
            workDir = self.ssh.workPath + '/' + self.ssh.workList[self.pos]
            # read file
            # cmd = 'ls -l ' + workDir
            cmd = 'screen-srv "' + workDir + '" 0 N'
            flist = self.ssh.getCmd(cmd)
            self.update_item.emit([len(flist)])
            for s in flist:
                # if len(s) < 2:
                #     continue
                ll = ast.literal_eval(eval(s))
                # ll = json.loads(s)
                # ll = s.split(',')
                # if len(ll) < 9:
                #     continue
                # ll = trimList(ll)
                # if ll[0][0] != '-':
                #     continue
                type = imgType(ll[1], ll[2])
                # read md5
                # md5 = self.ssh.getWorkFileMd5(workDir + '/' + ll[0])
                self.update_item.emit([ll[0], ll[1], ll[2], type, ll[3], ''])
                # self.update_item.emit([ll[8], 0, 0, 0, int(ll[4]), md5])
            self.ssh.sshClose()
        self.update_item.emit([])


class ScpDownloadWorkFromWeb(QThread):
    update_item = pyqtSignal(list)

    def __init__(self, webSsh, printSsh, webPath):
        super().__init__()
        self.web = webSsh
        self.print = printSsh
        self.path = webPath
        self.workDir = self.print.workPath + '/' + os.path.basename(webPath)
        self.workList = []
        self.webList = []

    def getPrintList(self):
        if self.print.sshConnect() == 0:
            # print建立目录
            cmd = 'mkdir "' + self.workDir + '"'
            self.print.getCmd(cmd)
            flist = self.print.getWorkDirMd5(self.workDir)
            self.workList = []
            for i, f in enumerate(flist):
                l = list(f.split('  '))
                if len(l) == 2:
                    self.workList.append(l)
            self.update_item.emit(['print', 'md5', str(len(flist))])
            self.print.sshClose()

    def getWebList(self):
        # print建立目录
        flist = self.web.getWorkDirMd5(self.path)
        self.webList = []
        for i, f in enumerate(flist):
            l = list(f.split('  '))
            if len(l) == 2:
                self.webList.append(l)
        self.update_item.emit(['web', 'md5', str(len(flist))])

    def run(self):
        # 读目录
        self.getPrintList()
        if self.web.sshConnect() == 0:
            self.getWebList()
            # scp /home/dashen/Work/work_1200/*.jpg root@192.168.1.8:/home/test/work_1200 -v
            # 多文件拷贝
            mName = ''
            n = 0
            for i, f in enumerate(self.webList):
                self.update_item.emit(['scp', os.path.basename(f[1]), str(int(i * 100 / len(self.webList)))])
                if len(self.workList) > i:
                    if self.workList[i][0] == self.webList[i][0]:
                        continue
                if mName == '':
                    mName = f[1][:-6]
                    n += 1
                    continue
                if mName == f[1][:-6]:
                    n += 1
                    continue
                # scp拷贝图片
                cmd = 'scp -q %s*.jpg %s@%s:%s' % (mName, self.print.user, self.print.ip, self.workDir)
                self.web.getCmd(cmd)
                mName = f[1][:-6]
                n = 1
            self.web.sshClose()
        self.update_item.emit([])


class WriteWorkImgFile(QThread):
    update_item = pyqtSignal(list)

    def __init__(self, loadSsh, srcList, srcPath, srcDir):
        super().__init__()
        self.ssh = loadSsh
        self.list = srcList
        self.path = srcPath
        self.dir = srcDir

    def run(self):
        # 读目录
        workDir = self.ssh.workPath + '/' + self.dir
        if self.ssh.sshConnect() == 0:
            # 建立目录
            cmd = 'mkdir "' + workDir + '"'
            self.ssh.getCmd(cmd)
            ssh = sshTransport(self.ssh.ip, self.ssh.port, self.ssh.user, self.ssh.password)
            ssh.sshConnect()
            # 拷贝图片
            self.update_item.emit([len(self.list)])
            for s in self.list:
                srcFile = self.path + '/' + self.dir + '/' + s[0]
                workFile = workDir + '/' + s[0]
                ssh.putFile(srcFile, workFile)
                ret = self.ssh.getWorkFileMd5(workFile)
                self.update_item.emit([s[0], 0, 0, 0, s[4], ret])
            ssh.sshClose()
            self.ssh.sshClose()
        self.update_item.emit([])


class sshClient():
    def __init__(self):
        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.status = -1
        self.ip = ''
        self.port = 0
        self.byteG = 0

    def __del__(self):
        self.sshClose()

    def setConf(self, ip, port, user, password, workpath):
        self.sshClose()
        self.ip = ip
        self.port = port
        self.user = user
        self.password = password
        self.workPath = workpath
        self.workList = []
        self.workLogList = {}
        self.workConfList = []
        self.workConfDefault = [0, 1, 2]
        self.devList = []

    def sshConnect(self):
        if self.status == 0:
            return self.status
        n = 0
        while True:
            try:
                self.ssh.connect(self.ip, self.port, self.user, self.password, timeout=1)
                self.status = 0
                break
            except Exception as e:
                self.status = -1
                saveLog('open sshConnect[%s:%s] 失败 %d' % (self.ip, e, n), log='error')
                if n >= 3:
                    break
            n += 1
        return self.status

    def sshClose(self):
        if self.status == 0:
            self.ssh.close()
        self.status = -1

    def sshSftpOpen(self):
        return self.ssh.open_sftp()

    def sshSftpClose(self, sftp):
        return sftp.close()

    def sshScpPutFile(self, user, ip, srcFile, desFile):
        # scp /home/dashen/Work/work_1200/*.jpg dashen@192.168.1.8:/home/test/work_1200 -v
        cmd = 'scp -q %s %s@%s:%s' % (srcFile, user, ip, desFile)
        return self.getCmd(cmd)

    def getDefaultConf(self, type):
        pos = self.workConfDefault[type]
        return self.getConfName(pos) + '.ini'

    def saveWorkLstLum(self, workName, lumDict):
        if self.sshConnect() == 0:
            workList = self.getWorkLst(workName)
            name = self.workPath + '/LST/' + workName + '.lst'
            try:
                sftp_client = self.sshSftpOpen()
                remote_file = sftp_client.open(name, 'w')
                for i, s in enumerate(workList):
                    if s[0] in lumDict:
                        s[8] = lumDict[s[0]]
                    remote_file.write('%s,%s,%s,%s,%s,%s,%s,%s,%s\n' % (s[0],
                                                                        s[1], s[2],
                                                                        s[3],
                                                                        s[4],
                                                                        s[5],
                                                                        s[6],
                                                                        s[7],
                                                                        s[8]))
                remote_file.close()
                sftp_client.close()
            except Exception as e:
                saveLog('open saveWorkLstLum[%s][%s:%s] 失败' % (workName, self.ip, e), log='error')
            self.sshClose()

    def saveWorkLstExpo(self, workName, expoDict):
        if self.sshConnect() == 0:
            workList = self.getWorkLst(workName)
            name = self.workPath + '/LST/' + workName + '.lst'
            try:
                sftp_client = self.sshSftpOpen()
                remote_file = sftp_client.open(name, 'w')
                for i, s in enumerate(workList):
                    if i in expoDict:
                        s[6] = str(expoDict[i])
                    remote_file.write('%s,%s,%s,%s,%s,%s,%s,%s,%s\n' % (s[0],
                                                                        s[1], s[2],
                                                                        s[3],
                                                                        s[4],
                                                                        s[5],
                                                                        s[6],
                                                                        s[7],
                                                                        s[8]))
                remote_file.close()
                sftp_client.close()
            except Exception as e:
                saveLog('open saveWorkLstExpo[%s][%s:%s] 失败' % (workName, self.ip, e), log='error')
            self.sshClose()

    def getWorkLst(self, workName, open=False, close=False):
        # 查询建立日志
        workList = []
        if open:
            self.sshConnect()
        if self.status == 0:
            name = self.workPath + '/LST/' + workName + '.lst'
            try:
                sftp_client = self.sshSftpOpen()
                remote_file = sftp_client.open(name, 'r')
                while True:
                    line = remote_file.readline()
                    if not line:
                        break
                    line = line.replace('\n', '')
                    line = line.replace('\r', '')
                    if len(line) == 0:
                        continue
                    flist = line.split(',')
                    workList.append(flist)
                remote_file.close()
                sftp_client.close()
            except Exception as e:
                saveLog('open getWorkLst[%s][%s:%s] 失败' % (workName, self.ip, e), log='error')
        if close:
            self.sshClose()
        return workList

    def getSshWebDirList(self, path):
        cmd = 'ls -l ' + path
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        res, err = stdout.read(), stderr.read()
        result = res if res else err
        str = result.decode()
        list = str.split('\n')
        dirList = []
        for s in list:
            slist = s.split()
            if len(slist) < 2:
                continue
            type = slist[0]
            name = slist[-1]
            if type[0] == 'd':
                dirList.append(name)
        return dirList

    def getSshWebImgList(self, path):
        cmd = 'ls -l ' + path
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        res, err = stdout.read(), stderr.read()
        result = res if res else err
        str = result.decode()
        list = str.split('\n')
        fileList = []
        byteList = []
        for s in list:
            slist = s.split()
            if len(slist) <= 2:
                continue
            type = slist[0]
            byte = int(slist[4])
            name = slist[-1]
            if type[0] == '-' and os.path.splitext(name)[1] in IMG_EXTS:
                fileList.append(name)
                byteList.append(byte)
        return fileList, byteList

    def getSshWebImg1List(self, path):
        cmd = 'screen-srv "' + path + '" 0 N'
        fileList = []
        flist = self.getCmd(cmd)
        for s in flist:
            ll = ast.literal_eval(eval(s))
            fileList.append([pathJoin(path, ll[0]), ll[1], ll[2], ll[5], ll[6], ll[9], ll[3]])
        return fileList

    def getSshWebImg0List(self, path):
        cmd = 'ls -1 ' + path
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        res, err = stdout.read(), stderr.read()
        result = res if res else err
        str = result.decode()
        list = str.split('\n')
        fileList = []
        for s in list:
            if len(s) < 2:
                continue
            if os.path.splitext(s)[1] in IMG_EXTS:
                fileList.append(pathJoin(path, s))
        return fileList

    def getSshWebFileList(self, path):
        cmd = 'ls -l ' + path
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        res, err = stdout.read(), stderr.read()
        result = res if res else err
        str = result.decode()
        list = str.split('\n')
        dirList = []
        csv = ''
        for s in list:
            slist = s.split()
            if len(slist) < 2:
                continue
            type = slist[0]
            name = slist[-1]
            work = ''
            try:
                if type[0] == 'd':
                    dirList.append(name)
                if csv == '' and type[0] == '-' and os.path.splitext(name)[1] == '.split':
                    csv = name
                    work = os.path.splitext(name)[0]
            except Exception as e:
                saveLog(curFunc(e), log='error')
        # dirList = winSort(dirList)
        # 目录排序
        dirList = natSort(dirList)
        list = []
        if len(work) > 0 and len(csv) > 0 and len(dirList) > 0:
            n = 1
            for s in dirList:
                if s[:len(work)] != work:
                    continue
                if n != int(s[len(work) + 1:]):
                    continue
                list.append(s)
                n += 1
        return list, csv, work

    def getWorkPrintJsonList(self):
        path = pathJoin(self.workPath, 'LOG')
        cmd = 'ls -l ' + path + '/*.json'
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        res, err = stdout.read(), stderr.read()
        result = res if res else err
        str = result.decode()
        list = str.split('\n')
        isM = False
        jdict = {}
        for s in list:
            if len(s) < 2:
                continue
            name = os.path.basename(s)
            f = os.path.splitext(name)
            if f[1] != '.json':
                continue
            wname = f[0][:-15]
            try:
                jdict[wname] += 1
            except Exception as e:
                jdict[wname] = 1
        for k, f in self.workLogList.items():
            try:
                nums = jdict[k]
                if f[0] != nums:
                    f[0] = nums
                    isM = True
            except Exception as e:
                pass
        return isM

    def getPrintJsonList(self):
        path = pathJoin(self.workPath, 'LOG')
        cmd = 'ls -1 ' + path + '/work_*.json'
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        res, err = stdout.read(), stderr.read()
        result = res if res else err
        str = result.decode()
        list = str.split('\n')
        jdict = {}
        for s in list:
            if len(s) < 2:
                continue
            name = os.path.basename(s)
            f = os.path.splitext(name)
            if f[1] != '.json':
                continue
            wname = f[0][:-15]
            wid = f[0][-14:]
            try:
                jdict[wname].append(wid)
            except Exception as e:
                jdict[wname] = [wid]
        return jdict

    def getWorkPrintJson(self, workName, workId):
        file = self.workPath + '/LOG/%s_%s.json' % (workName, workId)
        dict = {}
        try:
            sftp_client = self.sshSftpOpen()
            remote_file = sftp_client.open(file, 'r')
            jsonStr = remote_file.read()
            remote_file.close()
            sftp_client.close()
            dict = json.loads(jsonStr)
        except Exception as e:
            saveLog('get json [%s:%s] 失败' % (file, e), log='error')
        return dict

    def putWorkPrintJson(self, workName, workId, dict):
        file = self.workPath + '/LOG/%s_%s.json' % (workName, workId)
        jsonStr = ''
        try:
            sftp_client = self.sshSftpOpen()
            remote_file = sftp_client.open(file, 'w')
            jsonStr = json.dumps(dict, ensure_ascii=False)
            remote_file.write(jsonStr)
            remote_file.close()
            sftp_client.close()
        except Exception as e:
            saveLog('put json [%s:%s] 失败' % (file, e), log='error')
        return jsonStr

    def getWorkLogList(self):
        if self.sshConnect() != 0:
            return
        # 查询建立日志
        byteList = self.getDiskByte()
        self.workLogList = {}
        for f in self.workList:
            self.workLogList[f] = [0, '0000.00.00 00.00.00', 0, 0, 0, 0]
            if f in byteList.keys():
                self.workLogList[f][5] = byteList[f]
            # 打印次数，最后一次打印时间，打印类型，打印拍数，有效拍数，字节M
        workLog = self.workPath + '/LOG/work.log'
        isM = False
        sftp_client = self.sshSftpOpen()
        try:
            remote_file = sftp_client.open(workLog, 'r')
            while True:
                line = remote_file.readline()
                if not line:
                    break
                line = line.replace('\n', '')
                line = line.replace('\r', '')
                if len(line) == 0:
                    continue
                flist = line.split(',')
                if len(flist) <= 6:
                    # 无字节
                    isM = True
                    flist.append(str(0))
                # if int(flist[6]) == 0:
                #     isM = True
                if flist[0] in self.workLogList.keys():
                    self.workLogList[flist[0]] = [int(flist[1]),
                                                  flist[2],
                                                  findImgType(flist[3]),
                                                  int(flist[4]),
                                                  int(flist[5]),
                                                  self.workLogList[flist[0]][5]]
                else:
                    isM = True
            remote_file.close()
        except Exception as e:
            saveLog('open getWorkLogList[%s:%s] 失败' % (self.ip, e), log='error')
        for k, f in self.workLogList.items():
            if f[3] > 0:
                continue
            # 查看未记录项目
            path = pathJoin(self.workPath, k)
            nums1 = 0
            nums2 = 0
            try:
                flist = sftp_client.listdir(path)
                nums1 = len(flist)
                nums2 = 0
                for ss in flist:
                    if ss[:2] == '2_':
                        nums2 += 1
                stat = sftp_client.stat(path)
                dt = str(datetime.datetime.fromtimestamp(stat.st_mtime))
                f[3] = nums1
                f[4] = nums2
                f[1] = dt
                isM = True
            except Exception as e:
                saveLog('listdir_attr [%s:%s] 失败' % (path, e), log='error')
        # 获取日志打印数量
        if self.getWorkPrintJsonList():
            isM = True
        if isM:
            # 修改日志
            remote_file = sftp_client.open(workLog, 'w')
            for k, f in self.workLogList.items():
                remote_file.write('%s,%d,%s,%s,%d,%d,%d\n' % (k, f[0], f[1], getImgType0(f[2]), f[3], f[4], 0))
            remote_file.close()
        sftp_client.close()

    # 修改项目日志
    def putWorkLogList(self):
        if self.sshConnect() != 0:
            return
        workLog = self.workPath + '/LOG/work.log'
        try:
            sftp_client = self.sshSftpOpen()
            remote_file = sftp_client.open(workLog, 'w')
            for k, f in self.workLogList.items():
                remote_file.write('%s,%d,%s,%s,%d,%d,%d\n' % (k, f[0], f[1], getImgType0(f[2]), f[3], f[4], 0))
            remote_file.close()
            sftp_client.close()
        except Exception as e:
            saveLog('putWorkLog[%s:%s] 失败' % (workLog, e), log='error')
        self.sshClose()

    def delWorkLog(self, workName):
        if self.sshConnect() != 0:
            return
        workLog = self.workPath + '/LOG/work.log'
        try:
            sftp_client = self.sshSftpOpen()
            remote_file = sftp_client.open(workLog, 'w')
            for k, f in self.workLogList.items():
                if k != workName:
                    remote_file.write('%s,%d,%s,%s,%d,%d,%d\n' % (k, f[0], f[1], getImgType0(f[2]), f[3], f[4], 0))
            remote_file.close()
            sftp_client.close()
        except Exception as e:
            saveLog('delWorkLog[%s:%s] 失败' % (workLog, e), log='error')
        self.sshClose()

    def addWorkLog(self, workName, type, nums1, nums2):
        workLog = self.workPath + '/LOG/work.log'
        try:
            sftp_client = self.sshSftpOpen()
            remote_file = sftp_client.open(workLog, 'a+')
            remote_file.write('%s,0,%s,%s,%d,%d,%d\n' %
                              (workName, nowDateTimeStr(), getImgType0(type), nums1, nums2, 0))
            remote_file.close()
            sftp_client.close()
        except Exception as e:
            saveLog('open addWorkLog[%s:%s] 失败' % (self.ip, e), log='error')

    # def putWorkLogList(self, workName):
    #     workLog = self.workPath + '/LOG/work.log'
    #     # workNameLog = self.workPath + '/LOG/' + workName + '.log'
    #     try:
    #         sftp_client = self.sshSftpOpen()
    #         remote_file = sftp_client.open(workLog, 'a+')
    #         pass
    #         remote_file.close()
    #         sftp_client.close()
    #     except Exception as e:
    #         print('open [%s:%s] 失败' % (self.ip, e))

    def readTypeConf(self, type):
        name = self.getDefaultConf(type)
        return self.readConf(name)

    def readConf(self, confName):
        t = [0, 0, 0, 0, 0]
        s = [0, 0, 0, 0, 0]
        if self.sshConnect() != 0:
            return t, s
        keyt = ['ScreenExposure1=', 'ScreenExposure2=',
                'ScreenStop=', 'ScreenBlack=', 'ScreenFlickerNums=']
        keys = ['CanBeginStep=', 'CanBeginStepSpace=',
                'CanEndStep=', 'CanEndStepSpace=', 'CanPhotoDynamicsStep=']
        k = ['[SCREEN]', '[CANDEV]']
        key = ''
        try:
            sftp_client = self.sshSftpOpen()
            remote_file = sftp_client.open(confName, 'r')
            while True:
                line = remote_file.readline()
                if not line:
                    break
                line = line.replace('\n', '')
                line = line.replace('\r', '')
                line = line.replace(' ', '')
                if len(line) == 0:
                    continue
                if line[0] == '[':
                    key = ''
                    if line in k:
                        key = line
                else:
                    if key == '':
                        continue
                    if key == k[0]:
                        for i, kk in enumerate(keyt):
                            if line[:len(kk)] == kk:
                                t[i] = int(line[len(kk):])
                    else:
                        for i, kk in enumerate(keys):
                            if line[:len(kk)] == kk:
                                s[i] = int(line[len(kk):])
            remote_file.close()
            sftp_client.close()
        except Exception as e:
            saveLog('open readConf[%s:%s] 失败' % (self.ip, e), log='error')
        # self.sshClose()
        return t, s

    def getDiskUseByte(self):
        # 获取剩余空间
        cmd = 'df -H "' + self.workPath + '" |grep "/"'
        list = self.getCmd(cmd)
        byteG = 0
        if len(list) > 0:
            try:
                l = list[0].split()
                byteG = int(l[3][:-1])
            except Exception as e:
                saveLog('read ssh byte [%s:%s]' % (self.ip, e), log='error')
        return byteG

    def getDiskByte(self):
        # 获取目录空间
        cmd = 'du -m "' + self.workPath + '"'
        list = self.getCmd(cmd)
        bList = {}
        for b in list:
            bb = b.split()
            if len(bb) != 2:
                continue
            if pathJoin(self.workPath, 'work_') not in bb[1]:
                continue
            bList[os.path.basename(bb[1])] = int(bb[0])
        return bList

    def getDevList(self):
        if self.sshConnect() != 0:
            return -1, 0
        cmd = 'ls -1 ' + self.workPath
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        res, err = stdout.read(), stderr.read()
        result = res if res else err
        str = result.decode()
        list = str.split('\n')
        self.devList = []
        for s in list:
            if len(s) < 2:
                continue
            index = s.find('dev')
            if index < 0:
                continue
            if os.path.splitext(s)[1] != '.ini':
                continue
            self.devList.append(s)
        # self.sshClose()
        # self.devList = winSort(self.devList)
        self.devList = natSort(self.devList)
        id = self.getProcess('develop')
        return len(self.devList), id

    def getProcess(self, pexe):
        if self.sshConnect() != 0:
            return -1
        cmd = 'ps aux | grep "/home/dashen" | grep "%s"' % (pexe)
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        res, err = stdout.read(), stderr.read()
        result = res if res else err
        pstr = result.decode()
        plist = pstr.split('\n')
        pid = 0
        for s in plist:
            sl = s.split()
            if len(sl) < 11:
                continue
            if pexe in sl[10]:
                pid = int(sl[1])
                break
        # self.sshClose()
        return pid

    def getWorkConfListAll(self, log=False):
        if self.sshConnect() < 0:
            return -1, 0
        cmd = 'ls -l ' + self.workPath
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        res, err = stdout.read(), stderr.read()
        result = res if res else err
        str = result.decode()
        list = str.split('\n')
        self.workList = []
        self.workConfList = []
        for s in list:
            if len(s) < 2:
                continue
            index = s.find(' work_')
            if index < 0:
                continue
            if s[0] == 'd':
                name = s[index + 1:]
                # 临时目录
                if '.temp' == name[-5:]:
                    continue
                self.workList.append(name)
            elif s[0] == '-':
                flist = os.path.splitext(s[index + 1:])[0].split('_')
                name = flist[1]
                type = flist[2]
                isDef = 0
                if type[-1] == 'D':
                    isDef = 1
                    type = flist[2][:-1]
                self.workConfList.append([name, type, isDef])
                if name == 'default':
                    self.workConfDefault[findImgType(type)] = len(self.workConfList) - 1
        self.byteG = self.getDiskUseByte()
        id = self.getProcess('screen')
        if log:
            self.getWorkLogList()
        self.sshClose()
        return len(self.workList), id

    def getWorkName(self, name):
        return pathJoin(self.workPath, name)

    def getConfName(self, pos, name=''):
        file = self.workPath + '/work_' + (name if len(name) > 0 else self.workConfList[pos][0]) + '_' + \
               self.workConfList[pos][1]
        if self.workConfList[pos][2]:
            file += 'D'
        return file

    def addWorkConf(self, typeIndex):
        type = getImgType0(typeIndex)
        n = 0
        while True:
            file = '%s/work_conf%d_%s' % (self.workPath, n, type)
            cmd = 'ls %s.ini' % (file)
            str = self.execCmd(cmd)
            if '无法访问' in str:
                defFile = self.getConfName(self.workConfDefault[typeIndex])
                cmd = 'cp -n %s.ini %s.ini' % (defFile, file)
                self.execCmd(cmd)
                self.workConfList.append(['conf%d' % (n), '%s' % (type), 0])
                break
            n += 1
        return 1

    def delWorkConf(self, pos, name):
        # 删除配置
        if self.workConfList[pos][0] != name:
            return -1
        if self.sshConnect() != 0:
            return -1
        file = self.getConfName(pos)
        cmd = 'rm -f %s.ini' % (file)
        self.execCmd(cmd)
        del self.workConfList[pos]
        if self.workConfDefault[0] > pos:
            self.workConfDefault[0] -= 1
        if self.workConfDefault[1] > pos:
            self.workConfDefault[1] -= 1
        self.sshClose()
        return 0

    def setWorkConfDefault(self, pos, state):
        # 设置缺省配置
        if self.workConfList[pos][2] == state:
            return -1
        if self.sshConnect() != 0:
            return -1
        name1 = self.getConfName(pos)
        name2 = name1
        if self.workConfList[pos][2]:
            name2 = name2[:-1]
        else:
            name2 += 'D'
        cmd = 'mv %s.ini %s.ini' % (name1, name2)
        self.execCmd(cmd)
        self.workConfList[pos][2] = state
        # self.sshClose()
        return 0

    def setWorkConfName(self, pos, name):
        # 修改配置名称
        if self.workConfList[pos][0] == name:
            return -1
        if self.sshConnect() != 0:
            return -1
        name1 = self.getConfName(pos)
        name2 = self.getConfName(pos, name=name)
        cmd = 'mv %s.ini %s.ini' % (name1, name2)
        self.execCmd(cmd)
        self.workConfList[pos][0] = name
        # self.sshClose()
        return 0

    def retDirFileNums(self, dir):
        cmd = 'ls %s/*.jpg | wc -l' % (dir)
        return int(self.execCmd(cmd))

    def halt(self):
        self.execCmd('sudo init 0')

    def execCmd(self, cmd):
        str = ''
        if self.sshConnect() == 0:
            stdin, stdout, stderr = self.ssh.exec_command(cmd)
            res, err = stdout.read(), stderr.read()
            result = res if res else err
            str = result.decode()
            # self.sshClose()
        return str

    def getCmd(self, cmd):
        list = []
        if self.sshConnect() == 0:
            stdin, stdout, stderr = self.ssh.exec_command(cmd)
            res, err = stdout.read(), stderr.read()
            result = res if res else err
            str = result.decode()
            list = str.split('\n')
            list = trimList(list)
            # self.sshClose()
        return list

    def delWork(self, work):
        # 删除项目目录
        fpath = self.workPath + '/' + work
        cmd = 'rm -rf "' + fpath + '"'
        self.getCmd(cmd)
        # 删除LST文件
        fpath = self.workPath + '/LST/' + work + '.lst'
        cmd = 'rm -f "' + fpath + '"'
        self.getCmd(cmd)
        # 删除报告
        fpath = self.workPath + '/LOG/' + work + '*.json'
        cmd = 'rm -f ' + fpath + ''
        self.getCmd(cmd)
        # 更新项目日志
        self.getWorkConfListAll()
        self.delWorkLog(work)
        return 0

    def getWorkFileByte(self, file):
        cmd = 'ls -l "' + file + '"'
        ret = self.getCmd(cmd)[0]
        ret = ret.split(' ')
        if len(ret) > 4:
            return int(ret[4])
        else:
            return 0

    def getWorkFileMd5(self, file):
        cmd = 'md5sum "' + file + '"'
        ret = self.getCmd(cmd)[0]
        ret = ret.split(' ')
        return ret[0]

    def getWorkDirMd5(self, dir):
        cmd = 'md5sum "%s"/*' % (dir)
        ret = self.getCmd(cmd)
        return ret

    def getWorkImgFileNums(self, work, open=False, close=False):
        # 项目数量
        nums = 0
        if open:
            self.sshConnect()
        if self.status == 0:
            workDir = self.workPath + '/' + work
            cmd = 'ls -l "' + workDir + '" | grep "^-" |wc -l'
            ret = self.getCmd(cmd)
            nums = int(ret[0])
        if close:
            self.sshClose()
        return nums

    def getWorkImgFileList(self, work):
        # 项目列表
        fileList = []
        if self.sshConnect() == 0:
            workDir = self.workPath + '/' + work
            cmd = 'ls -l "' + workDir + '"'
            flist = self.getCmd(cmd)
            fileList = []
            for s in flist:
                if len(s) < 2:
                    continue
                ll = s.split(' ')
                if len(ll) < 9:
                    continue
                ll = trimList(ll)
                if ll[0][0] != '-':
                    continue
                fileList.append([ll[8], 0, 0, 0, int(ll[4]), ''])
            # self.sshClose()
        return fileList

    def getWorkFileList(self, work):
        # 项目列表
        n1 = 0
        n2 = 0
        fileList = []
        if self.sshConnect() == 0:
            cmd = 'ls -1 ' + '"' + self.workPath + '/' + work + '"'
            stdin, stdout, stderr = self.ssh.exec_command(cmd)
            res, err = stdout.read(), stderr.read()
            result = res if res else err
            str = result.decode()
            list = str.split('\n')
            list.sort(key=lambda x: x[:-4])
            llist = trimList(list)
            for s in llist:
                name = self.workPath + '/' + work + '/' + s
                fileList.append(name)
                n1 += 1
                if s[:2] == '2_':
                    n2 += 1
            # self.sshClose()
        return n1, n2, fileList


class sshTransport():
    def __init__(self, ip, port, user, password):
        self.user = user
        self.password = password
        self.transport = paramiko.Transport((ip, port))

    def sshConnect(self):
        self.transport.connect(username=self.user, password=self.password)
        self.sftp = paramiko.SFTPClient.from_transport(self.transport)

    def readJsonFile(self, name):
        data = '{}'
        try:
            f_size = self.sftp.stat(name).st_size
            with self.sftp.open(name, "r") as f:
                data = f.read(f_size)
        except Exception as e:
            saveLog(curFunc(e), log='error')
        return data

    def sshClose(self):
        self.transport.close()

    def getFile(self, src, des, call=None):
        return self.sftp.get(src, des, callback=call)

    def putFile(self, src, des, call=None):
        return self.sftp.put(src, des, callback=call)


# def remote_scp(host_ip,remote_path,local_path,username,password):
#     t = paramiko.Transport((host_ip,22))
#     t.connect(username=username, password=password) # 登录远程服务器
#     sftp = paramiko.SFTPClient.from_transport(t)# sftp传输协议
#     src = remote_path
#     des = local_path
#     sftp.get(src,des)
#     t.close()
#
# host_ip='xxx.xx.xx.xx' #不需要带端口
# username='xxx'
# password='xxx'
# remote_path=r'/root/xxx/xx.html'#远程文件名的路径
# local_path=r'./xx.html'#必须要带文件名，不带会出错。
# remote_scp(host_ip,remote_path,local_path,username,password)
#


def mp3Play(file):
    name = pathJoin(CONF_PATH, file + '.mp3')
    _thread = MP3Play(name)
    _thread.start()


# class MP3Play(QThread):
class MP3Play(threading.Thread):
    # update_item = pyqtSignal(float)
    def __init__(self, file):
        super().__init__()
        self.file = file
        # self.len = MP3(self.file).info.length
        # self.begin = 0.0

    def run(self):
        if not os.path.exists(self.file):
            return
        # pygame.mixer.init()
        # pygame.mixer.music.load(self.file)
        # pygame.mixer.music.play(start=self.begin)


class FlushSshServerScreen(QThread):
    update_item = pyqtSignal(list)
    done = pyqtSignal()

    def __init__(self, conf, key, user, out):
        super().__init__()
        self.conf = conf
        self.key = key
        self.super = user
        self.out = out

    def run(self):
        n = 0
        ssh = sshClient()
        var = self.conf.ScreenVar
        for i, s in enumerate(var['ScreenName']):
            ssh.setConf(var['ScreenIp'][i],
                        int(var['ScreenPort'][i]),
                        var['ScreenUser'][i],
                        var['ScreenPass'][i],
                        var['ScreenWorkPath'][i])
            if not self.super and not self.key.isScreenKey(var['ScreenKey'][i]):
                continue
            nums, pid = ssh.getWorkConfListAll()
            if nums < 0:
                self.update_item.emit([s, '失败'])
            else:
                self.update_item.emit([s, '成功'])
                n += 1
                self.update_item.emit([
                    s,
                    var['ScreenIp'][i],
                    int(var['ScreenPort'][i]),
                    var['ScreenUser'][i],
                    var['ScreenPass'][i],
                    var['ScreenWorkPath'][i],
                    i,
                    int(var['ScreenTcpPort'][i]),
                    int(var['ScreenReport'][i]),
                    pid])
            if self.out:
                break
        self.update_item.emit(['打印服务数 %d' % (n)])
        self.done.emit()
